use std::collections::HashMap;

use inkwell::AddressSpace;
use inkwell::IntPredicate;
use inkwell::builder::{Builder, BuilderError};
use inkwell::context::Context;
use inkwell::module::Module;
use inkwell::types::IntType;
use inkwell::values::{BasicMetadataValueEnum, FunctionValue, IntValue, PointerValue};

use crate::ast::{BinaryOp, Block, Expr, Function, GlobalVar, Item, Program, Stmt, Type, UnaryOp};
use crate::frontend::parse_program;

/// 将SysY源码翻译为LLVM IR字符串
pub fn compile_to_llvm_ir(source: &str, module_name: &str) -> Result<String, String> {
    let program = parse_program(source)?;
    let context = Context::create();
    let module = context.create_module(module_name);
    module.set_source_file_name(module_name);
    let i32_type = context.i32_type();
    let bool_type = context.bool_type();

    let mut generator = CodeGenerator {
        context: &context,
        module,
        i32_type,
        bool_type,
        functions: HashMap::new(),
        globals: HashMap::new(),
        const_env: HashMap::new(),
    };

    generator.declare_builtins();
    generator.declare_items(&program)?;
    generator.define_functions(&program)?;

    // verify module保证生成的IR合法
    if let Err(err) = generator.module.verify() {
        return Err(format!("生成的 LLVM IR 无效: {err}"));
    }
    Ok(generator.module.print_to_string().to_string())
}

struct CodeGenerator<'ctx> {
    context: &'ctx Context,
    module: Module<'ctx>,
    i32_type: IntType<'ctx>,
    bool_type: IntType<'ctx>,
    functions: HashMap<String, FunctionInfo<'ctx>>,
    globals: HashMap<String, PointerValue<'ctx>>,
    const_env: HashMap<String, i32>,
}

struct FunctionInfo<'ctx> {
    value: FunctionValue<'ctx>,
    ret_ty: Type,
}

impl<'ctx> CodeGenerator<'ctx> {
    fn declare_builtins(&mut self) {
        #[derive(Clone, Copy)]
        enum BuiltinParam {
            I32,
            I32Ptr,
        }

        let ptr_type = self.i32_type.ptr_type(AddressSpace::default());
        let void_type = self.context.void_type();

        let specs: &[(&str, Type, &[BuiltinParam])] = &[
            ("getint", Type::Int, &[]),
            ("getch", Type::Int, &[]),
            ("getarray", Type::Int, &[BuiltinParam::I32Ptr]),
            ("putint", Type::Void, &[BuiltinParam::I32]),
            ("putch", Type::Void, &[BuiltinParam::I32]),
            (
                "putarray",
                Type::Void,
                &[BuiltinParam::I32, BuiltinParam::I32Ptr],
            ),
            ("starttime", Type::Void, &[]),
            ("stoptime", Type::Void, &[]),
        ];

        for (name, ret_ty, params) in specs {
            if self.functions.contains_key(*name) {
                continue;
            }

            let param_types: Vec<_> = params
                .iter()
                .map(|param| match param {
                    BuiltinParam::I32 => self.i32_type.into(),
                    BuiltinParam::I32Ptr => ptr_type.into(),
                })
                .collect();

            let fn_type = match ret_ty {
                Type::Int => self.i32_type.fn_type(&param_types, false),
                Type::Void => void_type.fn_type(&param_types, false),
            };

            let function = self.module.add_function(name, fn_type, None);
            self.functions.insert(
                name.to_string(),
                FunctionInfo {
                    value: function,
                    ret_ty: *ret_ty,
                },
            );
        }
    }

    fn declare_items(&mut self, program: &Program) -> Result<(), String> {
        for item in &program.items {
            match item {
                Item::GlobalVar(var) => {
                    self.declare_global(var)?;
                }
                Item::Function(func) => {
                    self.declare_function(func)?;
                }
            }
        }
        Ok(())
    }

    fn define_functions(&mut self, program: &Program) -> Result<(), String> {
        for item in &program.items {
            if let Item::Function(func) = item {
                self.define_function(func)?;
            }
        }
        Ok(())
    }

    fn declare_global(&mut self, var: &GlobalVar) -> Result<(), String> {
        let init_value = if let Some(expr) = &var.init {
            Some(self.eval_const_expr(expr)?)
        } else {
            None
        };

        let global = self.module.add_global(self.i32_type, None, &var.name);
        let init_int = init_value.unwrap_or(0);
        let llvm_init = self.i32_type.const_int(init_int as u64, true);
        global.set_initializer(&llvm_init);
        global.set_alignment(4);
        if var.is_const {
            global.set_constant(true);
            self.const_env.insert(var.name.clone(), init_int);
        }
        self.globals
            .insert(var.name.clone(), global.as_pointer_value());
        Ok(())
    }

    fn declare_function(&mut self, func: &Function) -> Result<(), String> {
        if self.functions.contains_key(&func.name) {
            return Err(format!("重复定义函数 `{}`", func.name));
        }
        let fn_type = match func.ret_type {
            Type::Int => self
                .i32_type
                .fn_type(&vec![self.i32_type.into(); func.params.len()], false),
            Type::Void => self
                .context
                .void_type()
                .fn_type(&vec![self.i32_type.into(); func.params.len()], false),
        };
        let function = self.module.add_function(&func.name, fn_type, None);
        for (idx, param) in func.params.iter().enumerate() {
            let value = function
                .get_nth_param(idx as u32)
                .expect("参数索引应在范围内");
            value.set_name(&param.name);
        }
        self.functions.insert(
            func.name.clone(),
            FunctionInfo {
                value: function,
                ret_ty: func.ret_type,
            },
        );
        Ok(())
    }

    fn define_function(&mut self, func: &Function) -> Result<(), String> {
        let info = self
            .functions
            .get(&func.name)
            .ok_or_else(|| format!("函数 `{}` 未声明", func.name))?;
        let function = info.value;
        if function.count_basic_blocks() > 0 {
            return Err(format!("函数 `{}` 重复定义", func.name));
        }

        let entry = self.context.append_basic_block(function, "entry");
        let mut func_ctx = FunctionContext::new(self, function, entry, info.ret_ty);

        func_ctx.enter_scope();
        for (idx, param) in func.params.iter().enumerate() {
            let arg = function
                .get_nth_param(idx as u32)
                .expect("参数索引应在范围内")
                .into_int_value();
            let ptr = func_ctx.create_entry_alloca(&param.name)?;
            func_ctx
                .builder
                .build_store(ptr, arg)
                .map_err(builder_error)?;
            func_ctx
                .variables
                .last_mut()
                .expect("函数作用域存在")
                .insert(param.name.clone(), ptr);
        }
        func_ctx.gen_block(&func.body)?;

        // 若函数未显式返回，则生成默认返回
        if func_ctx.current_block().get_terminator().is_none() {
            match func.ret_type {
                Type::Int => {
                    return Err(format!("函数 `{}` 缺少返回语句", func.name));
                }
                Type::Void => {
                    func_ctx.builder.build_return(None).map_err(builder_error)?;
                }
            }
        }

        func_ctx.exit_scope();
        Ok(())
    }

    fn eval_const_expr(&self, expr: &Expr) -> Result<i32, String> {
        match expr {
            Expr::Int(value) => Ok(*value),
            Expr::Variable(name) => self
                .const_env
                .get(name)
                .copied()
                .ok_or_else(|| format!("常量表达式中使用了非常量 `{}`", name)),
            Expr::Unary { op, expr } => {
                let value = self.eval_const_expr(expr)?;
                match op {
                    UnaryOp::Pos => Ok(value),
                    UnaryOp::Neg => value
                        .checked_neg()
                        .ok_or_else(|| "整数取负溢出".to_string()),
                    UnaryOp::Not => Ok((value == 0) as i32),
                }
            }
            Expr::Binary { op, lhs, rhs } => {
                let left = self.eval_const_expr(lhs)?;
                let right = self.eval_const_expr(rhs)?;
                match op {
                    BinaryOp::Add => left
                        .checked_add(right)
                        .ok_or_else(|| "整数加法溢出".to_string()),
                    BinaryOp::Sub => left
                        .checked_sub(right)
                        .ok_or_else(|| "整数减法溢出".to_string()),
                    BinaryOp::Mul => left
                        .checked_mul(right)
                        .ok_or_else(|| "整数乘法溢出".to_string()),
                    BinaryOp::Div => {
                        if right == 0 {
                            Err("除以零".to_string())
                        } else {
                            Ok(left / right)
                        }
                    }
                    BinaryOp::Mod => {
                        if right == 0 {
                            Err("取模时除以零".to_string())
                        } else {
                            Ok(left % right)
                        }
                    }
                    BinaryOp::Lt => Ok((left < right) as i32),
                    BinaryOp::Le => Ok((left <= right) as i32),
                    BinaryOp::Gt => Ok((left > right) as i32),
                    BinaryOp::Ge => Ok((left >= right) as i32),
                    BinaryOp::Eq => Ok((left == right) as i32),
                    BinaryOp::Ne => Ok((left != right) as i32),
                    BinaryOp::And => {
                        if left == 0 {
                            Ok(0)
                        } else {
                            Ok((right != 0) as i32)
                        }
                    }
                    BinaryOp::Or => {
                        if left != 0 {
                            Ok(1)
                        } else {
                            Ok((right != 0) as i32)
                        }
                    }
                }
            }
            Expr::Call { name, .. } => Err(format!("常量表达式中不允许函数调用 `{name}`")),
        }
    }
}

struct FunctionContext<'ctx, 'cg> {
    codegen: &'cg mut CodeGenerator<'ctx>,
    function: FunctionValue<'ctx>,
    builder: Builder<'ctx>,
    alloca_builder: Builder<'ctx>,
    variables: Vec<HashMap<String, PointerValue<'ctx>>>,
    break_stack: Vec<inkwell::basic_block::BasicBlock<'ctx>>,
    continue_stack: Vec<inkwell::basic_block::BasicBlock<'ctx>>,
    ret_ty: Type,
}

impl<'ctx, 'cg> FunctionContext<'ctx, 'cg> {
    fn new(
        codegen: &'cg mut CodeGenerator<'ctx>,
        function: FunctionValue<'ctx>,
        entry: inkwell::basic_block::BasicBlock<'ctx>,
        ret_ty: Type,
    ) -> Self {
        let builder = codegen.context.create_builder();
        builder.position_at_end(entry);
        let alloca_builder = codegen.context.create_builder();
        alloca_builder.position_at_end(entry);
        Self {
            codegen,
            function,
            builder,
            alloca_builder,
            variables: Vec::new(),
            break_stack: Vec::new(),
            continue_stack: Vec::new(),
            ret_ty,
        }
    }

    fn enter_scope(&mut self) {
        self.variables.push(HashMap::new());
    }

    fn exit_scope(&mut self) {
        self.variables.pop();
    }

    fn current_block(&self) -> inkwell::basic_block::BasicBlock<'ctx> {
        self.builder
            .get_insert_block()
            .expect("当前应位于某个基本块中")
    }

    fn create_entry_alloca(&mut self, name: &str) -> Result<PointerValue<'ctx>, String> {
        self.alloca_builder
            .build_alloca(self.codegen.i32_type, name)
            .map_err(builder_error)
    }

    fn resolve_variable(&self, name: &str) -> Option<PointerValue<'ctx>> {
        for scope in self.variables.iter().rev() {
            if let Some(value) = scope.get(name) {
                return Some(*value);
            }
        }
        if let Some(global) = self.codegen.globals.get(name) {
            return Some(*global);
        }
        None
    }

    fn gen_block(&mut self, block: &Block) -> Result<(), String> {
        for stmt in &block.stmts {
            self.gen_stmt(stmt)?;
            if self.current_block().get_terminator().is_some() {
                break;
            }
        }
        Ok(())
    }

    fn gen_stmt(&mut self, stmt: &Stmt) -> Result<(), String> {
        match stmt {
            Stmt::VarDecl {
                is_const: _,
                name,
                init,
            } => {
                let ptr = self.create_entry_alloca(name)?;
                self.variables
                    .last_mut()
                    .expect("作用域应存在")
                    .insert(name.clone(), ptr);
                if let Some(expr) = init {
                    let value = {
                        let evaluated = self.gen_expr(expr)?;
                        self.expect_int(evaluated)?
                    };
                    self.builder
                        .build_store(ptr, value)
                        .map_err(builder_error)?;
                } else {
                    let zero = self.codegen.i32_type.const_zero();
                    self.builder.build_store(ptr, zero).map_err(builder_error)?;
                }
            }
            Stmt::Assign { name, expr } => {
                let ptr = self
                    .resolve_variable(name)
                    .ok_or_else(|| format!("未找到变量 `{}`", name))?;
                let value = {
                    let evaluated = self.gen_expr(expr)?;
                    self.expect_int(evaluated)?
                };
                self.builder
                    .build_store(ptr, value)
                    .map_err(builder_error)?;
            }
            Stmt::Expr(expr) => {
                let value = self.gen_expr(expr)?;
                if matches!(value, ExprValue::Void) {
                    // void 表达式无需处理
                }
            }
            Stmt::If {
                cond,
                then_branch,
                else_branch,
            } => {
                self.gen_if(cond, then_branch, else_branch.as_deref())?;
            }
            Stmt::While { cond, body } => {
                self.gen_while(cond, body)?;
            }
            Stmt::Break => {
                let target = self
                    .break_stack
                    .last()
                    .copied()
                    .ok_or_else(|| "break 不在循环内部".to_string())?;
                self.builder
                    .build_unconditional_branch(target)
                    .map_err(builder_error)?;
                self.start_unreachable_block("after_break");
            }
            Stmt::Continue => {
                let target = self
                    .continue_stack
                    .last()
                    .copied()
                    .ok_or_else(|| "continue 不在循环内部".to_string())?;
                self.builder
                    .build_unconditional_branch(target)
                    .map_err(builder_error)?;
                self.start_unreachable_block("after_continue");
            }
            Stmt::Return(expr) => match (expr, self.ret_ty) {
                (Some(e), Type::Int) => {
                    let value = {
                        let evaluated = self.gen_expr(e)?;
                        self.expect_int(evaluated)?
                    };
                    self.builder
                        .build_return(Some(&value))
                        .map_err(builder_error)?;
                }
                (None, Type::Int) => {
                    return Err("int 类型函数必须返回值".to_string());
                }
                (Some(_), Type::Void) => {
                    return Err("void 类型函数不应返回值".to_string());
                }
                (None, Type::Void) => {
                    self.builder.build_return(None).map_err(builder_error)?;
                }
            },
            Stmt::Block(block) => {
                self.enter_scope();
                self.gen_block(block)?;
                self.exit_scope();
            }
        }
        Ok(())
    }

    fn gen_if(
        &mut self,
        cond: &Expr,
        then_branch: &Stmt,
        else_branch: Option<&Stmt>,
    ) -> Result<(), String> {
        let parent = self.function;
        let then_block = self.codegen.context.append_basic_block(parent, "if_then");
        let else_block = if else_branch.is_some() {
            Some(self.codegen.context.append_basic_block(parent, "if_else"))
        } else {
            None
        };
        let merge_block = self.codegen.context.append_basic_block(parent, "if_merge");

        let cond_value = self.build_cond_value(cond)?;
        self.builder
            .build_conditional_branch(cond_value, then_block, else_block.unwrap_or(merge_block))
            .map_err(builder_error)?;

        self.builder.position_at_end(then_block);
        self.enter_scope();
        self.gen_stmt(then_branch)?;
        self.exit_scope();
        if self.current_block().get_terminator().is_none() {
            self.builder
                .build_unconditional_branch(merge_block)
                .map_err(builder_error)?;
        }

        if let Some(else_block) = else_block {
            self.builder.position_at_end(else_block);
            self.enter_scope();
            if let Some(stmt) = else_branch {
                self.gen_stmt(stmt)?;
            }
            self.exit_scope();
            if self.current_block().get_terminator().is_none() {
                self.builder
                    .build_unconditional_branch(merge_block)
                    .map_err(builder_error)?;
            }
        }

        self.builder.position_at_end(merge_block);
        Ok(())
    }

    fn gen_while(&mut self, cond: &Expr, body: &Stmt) -> Result<(), String> {
        let parent = self.function;
        let cond_block = self
            .codegen
            .context
            .append_basic_block(parent, "while_cond");
        let body_block = self
            .codegen
            .context
            .append_basic_block(parent, "while_body");
        let continue_block = cond_block;
        let exit_block = self.codegen.context.append_basic_block(parent, "while_end");

        self.builder
            .build_unconditional_branch(cond_block)
            .map_err(builder_error)?;

        self.builder.position_at_end(cond_block);
        let cond_value = self.build_cond_value(cond)?;
        self.builder
            .build_conditional_branch(cond_value, body_block, exit_block)
            .map_err(builder_error)?;

        self.builder.position_at_end(body_block);
        self.break_stack.push(exit_block);
        self.continue_stack.push(continue_block);
        self.enter_scope();
        self.gen_stmt(body)?;
        self.exit_scope();
        self.continue_stack.pop();
        self.break_stack.pop();

        if self.current_block().get_terminator().is_none() {
            self.builder
                .build_unconditional_branch(cond_block)
                .map_err(builder_error)?;
        }

        self.builder.position_at_end(exit_block);
        Ok(())
    }

    fn build_cond_value(&mut self, expr: &Expr) -> Result<IntValue<'ctx>, String> {
        let value = {
            let evaluated = self.gen_expr(expr)?;
            self.expect_int(evaluated)?
        };
        let zero = self.codegen.i32_type.const_zero();
        self.builder
            .build_int_compare(IntPredicate::NE, value, zero, "cond_tmp")
            .map_err(builder_error)
    }

    fn gen_expr(&mut self, expr: &Expr) -> Result<ExprValue<'ctx>, String> {
        match expr {
            Expr::Int(value) => {
                let v = self.codegen.i32_type.const_int(*value as u64, true);
                Ok(ExprValue::Int(v))
            }
            Expr::Variable(name) => {
                let ptr = self
                    .resolve_variable(name)
                    .ok_or_else(|| format!("未找到变量 `{}`", name))?;
                let load = self.builder.build_load(ptr, name).map_err(builder_error)?;
                Ok(ExprValue::Int(load.into_int_value()))
            }
            Expr::Unary { op, expr } => {
                let value = {
                    let evaluated = self.gen_expr(expr)?;
                    self.expect_int(evaluated)?
                };
                let result = match op {
                    UnaryOp::Pos => value,
                    UnaryOp::Neg => self
                        .builder
                        .build_int_neg(value, "neg_tmp")
                        .map_err(builder_error)?,
                    UnaryOp::Not => {
                        let cmp = self
                            .builder
                            .build_int_compare(
                                IntPredicate::EQ,
                                value,
                                self.codegen.i32_type.const_zero(),
                                "not_cmp",
                            )
                            .map_err(builder_error)?;
                        self.builder
                            .build_int_z_extend(cmp, self.codegen.i32_type, "not_tmp")
                            .map_err(builder_error)?
                    }
                };
                Ok(ExprValue::Int(result))
            }
            Expr::Binary { op, lhs, rhs } => self.gen_binary(op, lhs, rhs),
            Expr::Call { name, args } => {
                let (function_value, ret_ty) = self
                    .codegen
                    .functions
                    .get(name)
                    .map(|info| (info.value, info.ret_ty))
                    .ok_or_else(|| format!("未找到函数 `{}`", name))?;
                let mut arg_values = Vec::with_capacity(args.len());
                for arg in args {
                    let value = {
                        let evaluated = self.gen_expr(arg)?;
                        self.expect_int(evaluated)?
                    };
                    arg_values.push(BasicMetadataValueEnum::from(value));
                }
                let call = self
                    .builder
                    .build_call(function_value, &arg_values, &format!("call_{name}"))
                    .map_err(builder_error)?;
                match ret_ty {
                    Type::Int => {
                        let ret = call
                            .try_as_basic_value()
                            .left()
                            .ok_or_else(|| format!("函数 `{}` 返回值获取失败", name))?
                            .into_int_value();
                        Ok(ExprValue::Int(ret))
                    }
                    Type::Void => Ok(ExprValue::Void),
                }
            }
        }
    }

    fn gen_binary(
        &mut self,
        op: &BinaryOp,
        lhs: &Expr,
        rhs: &Expr,
    ) -> Result<ExprValue<'ctx>, String> {
        match op {
            BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => {
                let left = {
                    let value = self.gen_expr(lhs)?;
                    self.expect_int(value)?
                };
                let right = {
                    let value = self.gen_expr(rhs)?;
                    self.expect_int(value)?
                };
                let result = match op {
                    BinaryOp::Add => self
                        .builder
                        .build_int_add(left, right, "add_tmp")
                        .map_err(builder_error)?,
                    BinaryOp::Sub => self
                        .builder
                        .build_int_sub(left, right, "sub_tmp")
                        .map_err(builder_error)?,
                    BinaryOp::Mul => self
                        .builder
                        .build_int_mul(left, right, "mul_tmp")
                        .map_err(builder_error)?,
                    BinaryOp::Div => self
                        .builder
                        .build_int_signed_div(left, right, "div_tmp")
                        .map_err(builder_error)?,
                    BinaryOp::Mod => self
                        .builder
                        .build_int_signed_rem(left, right, "mod_tmp")
                        .map_err(builder_error)?,
                    _ => unreachable!(),
                };
                Ok(ExprValue::Int(result))
            }
            BinaryOp::Lt
            | BinaryOp::Le
            | BinaryOp::Gt
            | BinaryOp::Ge
            | BinaryOp::Eq
            | BinaryOp::Ne => {
                let left = {
                    let value = self.gen_expr(lhs)?;
                    self.expect_int(value)?
                };
                let right = {
                    let value = self.gen_expr(rhs)?;
                    self.expect_int(value)?
                };
                let predicate = match op {
                    BinaryOp::Lt => IntPredicate::SLT,
                    BinaryOp::Le => IntPredicate::SLE,
                    BinaryOp::Gt => IntPredicate::SGT,
                    BinaryOp::Ge => IntPredicate::SGE,
                    BinaryOp::Eq => IntPredicate::EQ,
                    BinaryOp::Ne => IntPredicate::NE,
                    _ => unreachable!(),
                };
                let cmp = self
                    .builder
                    .build_int_compare(predicate, left, right, "cmp_tmp")
                    .map_err(builder_error)?;
                let ext = self
                    .builder
                    .build_int_z_extend(cmp, self.codegen.i32_type, "cmp_ext")
                    .map_err(builder_error)?;
                Ok(ExprValue::Int(ext))
            }
            BinaryOp::And => {
                let value = self.build_logic_and(lhs, rhs)?;
                Ok(ExprValue::Int(value))
            }
            BinaryOp::Or => {
                let value = self.build_logic_or(lhs, rhs)?;
                Ok(ExprValue::Int(value))
            }
        }
    }

    fn build_logic_and(&mut self, lhs: &Expr, rhs: &Expr) -> Result<IntValue<'ctx>, String> {
        let function = self.function;
        let lhs_val = {
            let value = self.gen_expr(lhs)?;
            self.expect_int(value)?
        };
        let lhs_block = self.builder.get_insert_block().expect("当前应位于基本块");
        let lhs_cond = self
            .builder
            .build_int_compare(
                IntPredicate::NE,
                lhs_val,
                self.codegen.i32_type.const_zero(),
                "and_lhs_cond",
            )
            .map_err(builder_error)?;

        let rhs_block = self.codegen.context.append_basic_block(function, "and_rhs");
        let merge_block = self
            .codegen
            .context
            .append_basic_block(function, "and_merge");

        self.builder
            .build_conditional_branch(lhs_cond, rhs_block, merge_block)
            .map_err(builder_error)?;

        self.builder.position_at_end(rhs_block);
        let rhs_val = {
            let value = self.gen_expr(rhs)?;
            self.expect_int(value)?
        };
        let rhs_cond = self
            .builder
            .build_int_compare(
                IntPredicate::NE,
                rhs_val,
                self.codegen.i32_type.const_zero(),
                "and_rhs_cond",
            )
            .map_err(builder_error)?;
        self.builder
            .build_unconditional_branch(merge_block)
            .map_err(builder_error)?;
        let rhs_block_end = self
            .builder
            .get_insert_block()
            .expect("逻辑与右侧基本块应存在");

        self.builder.position_at_end(merge_block);
        let phi = self
            .builder
            .build_phi(self.codegen.bool_type, "and_phi")
            .map_err(builder_error)?;
        phi.add_incoming(&[
            (&self.codegen.bool_type.const_zero(), lhs_block),
            (&rhs_cond, rhs_block_end),
        ]);

        let result = self
            .builder
            .build_int_z_extend(
                phi.as_basic_value().into_int_value(),
                self.codegen.i32_type,
                "and_ext",
            )
            .map_err(builder_error)?;
        Ok(result)
    }

    fn build_logic_or(&mut self, lhs: &Expr, rhs: &Expr) -> Result<IntValue<'ctx>, String> {
        let function = self.function;
        let lhs_val = {
            let value = self.gen_expr(lhs)?;
            self.expect_int(value)?
        };
        let lhs_block = self.builder.get_insert_block().expect("当前应位于基本块");
        let lhs_cond = self
            .builder
            .build_int_compare(
                IntPredicate::NE,
                lhs_val,
                self.codegen.i32_type.const_zero(),
                "or_lhs_cond",
            )
            .map_err(builder_error)?;

        let rhs_block = self.codegen.context.append_basic_block(function, "or_rhs");
        let merge_block = self
            .codegen
            .context
            .append_basic_block(function, "or_merge");

        self.builder
            .build_conditional_branch(lhs_cond, merge_block, rhs_block)
            .map_err(builder_error)?;

        self.builder.position_at_end(rhs_block);
        let rhs_val = {
            let value = self.gen_expr(rhs)?;
            self.expect_int(value)?
        };
        let rhs_cond = self
            .builder
            .build_int_compare(
                IntPredicate::NE,
                rhs_val,
                self.codegen.i32_type.const_zero(),
                "or_rhs_cond",
            )
            .map_err(builder_error)?;
        self.builder
            .build_unconditional_branch(merge_block)
            .map_err(builder_error)?;
        let rhs_block_end = self
            .builder
            .get_insert_block()
            .expect("逻辑或右侧基本块应存在");

        self.builder.position_at_end(merge_block);
        let phi = self
            .builder
            .build_phi(self.codegen.bool_type, "or_phi")
            .map_err(builder_error)?;
        phi.add_incoming(&[
            (&self.codegen.bool_type.const_all_ones(), lhs_block),
            (&rhs_cond, rhs_block_end),
        ]);

        let result = self
            .builder
            .build_int_z_extend(
                phi.as_basic_value().into_int_value(),
                self.codegen.i32_type,
                "or_ext",
            )
            .map_err(builder_error)?;
        Ok(result)
    }

    fn expect_int(&self, value: ExprValue<'ctx>) -> Result<IntValue<'ctx>, String> {
        match value {
            ExprValue::Int(v) => Ok(v),
            ExprValue::Void => Err("void 表达式不能用于需要整数值的上下文".to_string()),
        }
    }

    fn start_unreachable_block(&mut self, name: &str) {
        let block = self.codegen.context.append_basic_block(self.function, name);
        self.builder.position_at_end(block);
    }
}

fn builder_error(err: BuilderError) -> String {
    err.to_string()
}

enum ExprValue<'ctx> {
    Int(IntValue<'ctx>),
    Void,
}
